<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Controller;

use App\Logic\UserLogic;
use App\Middleware\AuthMiddleware;
use App\Model\EmailLog;
use App\Model\SmsLog;
use App\Model\User;
use App\Service\UploadService;
use App\Utils\Enum\SceneEnum;
use App\Utils\Enum\UserEnum;
use Exception;
use Hyperf\Context\Context;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
use Psr\Http\Message\ResponseInterface;
use Throwable;

#[AutoController]
class UserController extends AbstractController
{
    /**
     * 注册信息预检查.
     */
    public function checkRegInfo(): ResponseInterface
    {
        $input = $this->request->all();
        if (!empty($input['username']) && User::query()->where('username', $input['username'])->exists()) {
            return $this->apiReturn(400, '该用户已被使用');
        }
        if (!empty($input['mobile']) && User::query()->where('mobile', $input['mobile'])->exists()) {
            return $this->apiReturn(400, '该手机号码已被使用');
        }
        if (!empty($input['email']) && User::query()->where('email', $input['email'])->exists()) {
            return $this->apiReturn(400, '该邮箱地址已被使用');
        }
        return $this->apiReturn();
    }

    /**
     * 注册账号.
     */
    public function reg(): ResponseInterface
    {
        $input = $this->request->all();
        if (empty($input['username']) || empty($input['password']) || strlen($input['password']) != 32
            || ($input['regType'] == 'mobile' && (!preg_match('/^1\d{10}$/', $input['mobile']) || empty($input['code'])))
            || ($input['regType'] == 'email') && (!filter_var($input['email'], FILTER_VALIDATE_EMAIL) || empty($input['code']))) {
            return $this->apiReturn(400, '参数错误');
        }

        if (User::isExists('username', $input['username'])) {
            return $this->apiReturn(400, '该用户名已被使用');
        }

        // 手机号码注册
        if ($input['regType'] == 'mobile') {
            if (User::isExists('mobile', $input['mobile'])) {
                return $this->apiReturn(400, '该手机号码已被使用');
            }
            if (!$validId = validate_sms_code(SceneEnum::REGISTER, $input['mobile'], $input['code'])) {
                return $this->apiReturn(400, '手机验证码错误');
            }
            SmsLog::setValid($validId);
        } // 邮箱地址注册
        elseif ($input['regType'] == 'email') {
            if (User::isExists('email', $input['email'])) {
                return $this->apiReturn(400, '该邮箱已被使用');
            }
            if (!$validId = validate_email_code(SceneEnum::REGISTER, $input['email'], $input['code'])) {
                return $this->apiReturn(400, '邮箱验证码错误');
            }
            EmailLog::setValid($validId);
        } else {
            return $this->apiReturn(400, '不支持该注册方式');
        }

        try {
            $client = $this->request->header('client', '0');
            $user = UserLogic::register($input, $client);
            $token = UserLogic::createToken($user, $client);
            if ($token) {
                $userInfo = User::find($user['id']);
                return $this->apiReturn(200, '注册成功', [
                    'token' => $token,
                    'userInfo' => UserLogic::formatUserInfo($userInfo, true)
                ]);
            }
            return $this->apiReturn(403, '注册成功，请前往登录');
        } catch (Exception $e) {
            return $this->apiReturn(400, $e->getMessage());
        }
    }

    /**
     * 登录.
     */
    public function login(): ResponseInterface
    {
        $input = $this->request->all();
        try {
            $input['client'] = $this->request->header('client', '0');
            switch ($input['loginType']) {
                case UserEnum::LOGIN_TYPE_ACCOUNT:
                    $ret = UserLogic::accountLogin($input);
                    break;
                case UserEnum::LOGIN_TYPE_MOBILE:
                    $ret = UserLogic::mobileLogin($input);
                    break;
                case UserEnum::LOGIN_TYPE_OPT:
                    $ret = UserLogic::otpLogin($input);
                    break;
                default:
                    return $this->apiReturn(400, '暂不支持该登录方式');
            }
            if ($ret) {
                return $this->apiReturn(200, '登录成功', $ret);
            }
            return $this->apiReturn(400, '登录失败');
        } catch (Exception $e) {
            return $this->apiReturn(400, '登录失败:' . $e->getMessage());
        }
    }

    /**
     * 修改密码
     */
    #[Middleware(AuthMiddleware::class)]
    public function changePassword(): ResponseInterface
    {
        $userid = Context::get('userid', 0);
        $input = $this->request->all();
        if (empty($input['oldPassword']) || empty($input['newPassword']) || strlen($input['newPassword']) != 32) {
            return $this->apiReturn(400, '参数错误');
        }
        try {
            UserLogic::changePassword($userid, $input['oldPassword'], $input['newPassword']);
            return $this->apiReturn(200, '修改成功');
        } catch (Exception $e) {
            return $this->apiReturn(400, $e->getMessage());
        }
    }

    /**
     * 重置密码
     */
    public function resetPwd()
    {
        $input = $this->request->all();
        if ($input['resetType'] == 'mobile' && (empty($input['mobile']) || empty($input['code'])) || $input['resetType'] == 'email' && (empty($input['email']) || empty($input['code'])) || strlen($input['password']) < 6) {
            return $this->apiReturn(400, '参数错误');
        }
        if ($input['resetType'] == 'mobile') {
            $user = User::query()->where('mobile', $input['mobile'])->first();
            if (!$user) {
                return $this->apiReturn(400, '手机号码不存在');
            }
            if (!$smsValidId = validate_sms_code(SceneEnum::RESET_PASSWORD, $input['mobile'], $input['code'])) {
                SmsLog::setValid($smsValidId);
                return $this->apiReturn(400, '验证码错误');
            }
        } elseif ($input['resetType'] == 'email') {
            $user = User::query()->where('email', $input['email'])->first();
            if (!$user) {
                return $this->apiReturn(400, '邮箱地址不存在');
            }
            if (!$emailValidId = validate_email_code(SceneEnum::RESET_PASSWORD, $input['email'], $input['code'])) {
                EmailLog::setValid($emailValidId);
                return $this->apiReturn(400, '验证码错误');
            }
        } else {
            return $this->apiReturn(400, '不支持通过该方式重置密码');
        }
        try {
            UserLogic::resetPassword($user['id'], $input['password']);
            return $this->apiReturn(200, '重置成功');
        } catch (Throwable $e) {
            return $this->apiReturn(400, $e->getMessage());
        }
    }

    /**
     * 绑定邮箱.
     */
    #[Middleware(AuthMiddleware::class)]
    public function bindEmail()
    {
        $email = Context::get('email');
        $userid = Context::get('userid');
//        if (!empty($email)) {
//            return $this->apiReturn(400, '当前已绑定了邮箱');
//        }
        $input = $this->request->all();
        if (empty($input['email']) || empty($input['code'])) {
            return $this->apiReturn(400, '参数错误');
        }
        if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) {
            return $this->apiReturn(400, '邮箱地址格式错误');
        }
        if (User::where([['email', '=', $input['email']], ['id', '!=', $userid]])->exists()) {
            return $this->apiReturn(400, '该邮箱地址已被其他账号绑定');
        }
        if (!$validId = validate_email_code(SceneEnum::BIND_EMAIL, $input['email'], $input['code'])) {
            EmailLog::setValid($validId);
            return $this->apiReturn(400, '验证码错误');
        }
        if (!User::where('id', $userid)->update(['email' => $input['email']])) {
            return $this->apiReturn(400, '邮箱绑定失败');
        }
        EmailLog::setValid($validId);
        UserLogic::createLog($userid, 'bindEmail', ['email' => $input['email']]);
        UserLogic::updateTokenInfo($userid);
        return $this->apiReturn(200, '绑定成功');
    }

    /**
     * 解绑邮箱.
     */
    #[Middleware(AuthMiddleware::class)]
    public function unbindEmail()
    {
        $email = Context::get('email');
        $userid = Context::get('userid');
        if (empty($email)) {
            return $this->apiReturn(400, '未绑定邮箱地址');
        }
        $input = $this->request->all();
        if (empty($input['email']) || empty($input['email_code'])) {
            return $this->apiReturn(400, '参数错误');
        }
        if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) {
            return $this->apiReturn(400, '邮箱地址格式错误');
        }
        if (!$validId = validate_email_code(SceneEnum::UNBIND_EMAIL, $input['email'], $input['email_code'])) {
            EmailLog::setValid($validId);
            return $this->apiReturn(400, '验证码错误');
        }
        if (!User::where('id', $userid)->update(['email' => ''])) {
            return $this->apiReturn(400, '邮箱解绑失败');
        }
        EmailLog::setValid($validId);
        UserLogic::createLog($userid, 'unbindEmail', ['email' => $input['email']]);
        UserLogic::updateTokenInfo($userid);
        return $this->apiReturn(200, '解绑成功');
    }

    /**
     * 绑定手机号码
     */
    #[Middleware(AuthMiddleware::class)]
    public function bindMobile(): ResponseInterface
    {
        $mobile = Context::get('mobile');
        $userid = Context::get('userid');
//        if (!empty($mobile)) {
//            return $this->apiReturn(400, '当前已绑定了手机号码');
//        }
        $input = $this->request->all();
        if (empty($input['mobile']) || empty($input['code'])) {
            return $this->apiReturn(400, '参数错误');
        }
        if (!preg_match('/^1\d{10}$/', $input['mobile'])) {
            return $this->apiReturn(400, '手机号码格式错误');
        }
        if (User::where([['mobile', '=', $input['mobile']], ['id', '!=', $userid]])->exists()) {
            return $this->apiReturn(400, '该手机号码已被其他账号绑定');
        }
        if (!$validId = validate_sms_code(SceneEnum::BIND_MOBILE, $input['mobile'], $input['code'])) {
            SmsLog::setValid($validId);
            return $this->apiReturn(400, '验证码错误');
        }
        if (!User::where('id', $userid)->update(['mobile' => $input['mobile']])) {
            return $this->apiReturn(400, '手机号码绑定失败');
        }
        SmsLog::setValid($validId);
        UserLogic::createLog($userid, 'bindMobile', ['mobile' => $input['mobile']]);
        UserLogic::updateTokenInfo($userid);
        return $this->apiReturn(200, '绑定成功');
    }

    /**
     * 解绑手机.
     */
    #[Middleware(AuthMiddleware::class)]
    public function unbindMobile(): ResponseInterface
    {
        $mobile = Context::get('mobile');
        $userid = Context::get('userid');
        if (empty($mobile)) {
            return $this->apiReturn(400, '未绑定手机号码');
        }
        $input = $this->request->all();
        if (empty($input['mobile']) || empty($input['code'])) {
            return $this->apiReturn(400, '参数错误');
        }
        if (!$validId = validate_sms_code(SceneEnum::UNBIND_MOBILE, $input['mobile'], $input['code'])) {
            SmsLog::setValid($validId);
            return $this->apiReturn(400, '验证码错误');
        }
        if (!User::where('id', $userid)->update(['mobile' => ''])) {
            return $this->apiReturn(400, '手机号码解绑失败');
        }
        SmsLog::setValid($validId);
        UserLogic::createLog($userid, 'unbindMobile', ['mobile' => $input['mobile']]);
        UserLogic::updateTokenInfo($userid);
        return $this->apiReturn(200, '解绑成功');
    }

    /**
     * 我的关注.
     */
    #[Middleware(AuthMiddleware::class)]
    public function myFollow(): ResponseInterface
    {
        $userid = Context::get('userid', 0);
        $input = $this->request->all();
        $data = UserLogic::getMyFollowAnchorList($userid, $input);
        return $this->apiReturn(200, 'succ', $data);
    }

    /**
     * 获取个人信息.
     */
    #[Middleware(AuthMiddleware::class)]
    public function getProfile(): ResponseInterface
    {
        $userid = Context::get('userid');
        $user = User::find($userid);
        return $this->apiReturn(200, 'succ', UserLogic::formatUserInfo($user, true));
    }

    /**
     * 获取任务列表（含签到）.
     */
    #[Middleware(AuthMiddleware::class)]
    public function getTaskList(): ResponseInterface
    {
        $userid = Context::get('userid');
        $taskInfo = UserLogic::getUserTaskInfo($userid);
        $signInfo = UserLogic::getSignRecord($userid);
        return $this->apiReturn(200, 'succ', [
            'taskInfo' => $taskInfo,
            'signInfo' => $signInfo,
        ]);
    }

    /**
     * 签到.
     */
    #[Middleware(AuthMiddleware::class)]
    public function sign(): ResponseInterface
    {
        $userid = Context::get('userid');
        try {
            $result = UserLogic::sign($userid);
            return $this->apiReturn(200, '签到成功', $result);
        } catch (Exception $e) {
            return $this->apiReturn(400, $e->getMessage());
        }
    }

    /**
     * 获取金币明细.
     */
    #[Middleware(AuthMiddleware::class)]
    public function getCoinRecord(): ResponseInterface
    {
        $userid = Context::get('userid');
        return $this->apiReturn(200, 'succ', UserLogic::getCoinRecords($userid, $this->request->all()));
    }

    /**
     * 获取积分明细.
     */
    #[Middleware(AuthMiddleware::class)]
    public function getIntegralRecord(): ResponseInterface
    {
        $userid = Context::get('userid');
        return $this->apiReturn(200, 'succ', UserLogic::getIntegralRecords($userid, $this->request->all()));
    }

    /**
     * 获取用户模块配置.
     */
    public function getUserSetting(): ResponseInterface
    {
        return $this->apiReturn(200, 'succ', UserLogic::getSetting());
    }

    /**
     * 上传头像.
     */
    #[Middleware(AuthMiddleware::class)]
    public function uploadAvatar(): ResponseInterface
    {
        $userid = Context::get('userid', 0);
        $file = $this->request->file('file');
        try {
            $info = $this->container->get(UploadService::class)->image($file);
            User::query()->where('id', $userid)->update(['avatar' => $info['path']]);
            return $this->apiReturn(200, '上传成功');
        } catch (Exception|Throwable $e) {
            return $this->apiReturn(400, $e->getMessage());
        }
    }

    /**
     * 设置默认头像
     * @return ResponseInterface
     */
    #[Middleware(AuthMiddleware::class)]
    public function updateDefaultAvatar(): ResponseInterface
    {
        $userid = Context::get('userid', 0);
        $id = $this->request->input('id', 1);
        $imgId = min(max(1, intval($id)), 10);
        User::query()->where('id', $userid)->update(['avatar' => 'default_avatar/' . str_pad((string)$imgId, 3, '0', STR_PAD_LEFT) . '.jpg']);
        return $this->apiReturn(200, '保存成功');
    }

    /**
     * 我的优惠券.
     */
    #[Middleware(AuthMiddleware::class)]
    public function myCoupon(): ResponseInterface
    {
        $records = UserLogic::getCouponList(Context::get('userid'), $this->request->all());
        return $this->apiReturn(200, 'succ', $records);
    }

    /**
     * 修改昵称
     */
    #[Middleware(AuthMiddleware::class)]
    public function updateNickName(): ResponseInterface
    {
        $nickName = $this->request->input('nickName');
        if (empty($nickName)) {
            return $this->apiReturn(400, '昵称不能为空');
        }
        if (mb_strlen($nickName) < 4) {
            return $this->apiReturn(400, '昵称长度不可少于4个字');
        }

        try {
            $userid = Context::get('userid', 0);
            UserLogic::modifyUserNickName($userid, $nickName);
            return $this->apiReturn(200, '修改成功');
        } catch (Exception $e) {
            return $this->apiReturn(400, $e->getMessage());
        }
    }

    /**
     * 执行任务
     * @return ResponseInterface
     */
    public function doTask(): ResponseInterface
    {
        $this->parseToken();
        $userId = Context::get('userid', 0);
        $taskType = $this->request->input('taskType', 0);
        if (!$userId || !$taskType) {
            return $this->apiReturn(200, 'succ');
        }
        $data = ['status' => true];
        $result = UserLogic::doTask($userId, $taskType);
        if (is_array($result)) {
            $data = array_merge($data, $result);
        }
        return $this->apiReturn(200, 'succ', $data);
    }
}
